﻿// demon11-string-1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。

//模板：

//模板是泛型编程的基础,模板不能定义和声明分离，也不能定义和分离在两个文件，

/*
#include <iostream>
using namespace std;

void Swap(int&left ,int&right)
{
    int tmp = left;
    left = right;
    right = tmp;
}

void Swap(double& left, double& right)
{
    double tmp = left;
    left = right;
    right = tmp;
}

void Swap(char& left, char& right)
{
    char tmp = left;
    left = right;
    right = tmp;
}

int main()
{
    int i = 1, j = 3;
    cout << "交换前i = " << i << ",j = " << j << endl;
    Swap(i, j);
    cout << "交换后i = " << i << ",j = " << j << endl<<endl;

    double a = 1.5, b = 3.7;
    cout << "交换前a = " << a << ",b = " << b << endl;
    Swap(a, b);
    cout << "交换后a = " << a << ",b = " << b << endl << endl;

    char x = 'x', y = 'y';
    cout << "交换前x = " << x << ",y = " << y << endl;
    Swap(x, y);
    cout << "交换后x = " << x << ",y = " << y << endl;
}
*/

//使用模板来优化上述代码
/*
#include<iostream>
using namespace std;

//使用函数模板
template<typename T>
void Swap(T& left, T& right)
{
    T tmp = left;
    left = right;
    right = tmp;
}

int main()
{
    char x = 'x', y = 'y';
    double a = 1.6, b = 1.7;
    int i = 3, j = 8;
    cout << "交换前:\nx = " << x << ",y = " << y << endl;
    cout << "a = " << a << ",b = " << b << endl;
    cout << "i = " << i << ",j = " << j << endl << endl;
    //使用模板
    Swap(x, y);
    Swap(a, b);
    Swap(i, j);

    cout << "交换后:\nx = " << x << ",y = " << y << endl;
    cout << "a = " << a << ",b = " << b << endl;
    cout << "i = " << i << ",j = " << j << endl<<endl;

    //调用库函数
    int cc = 16, dd = 17;
    cout << "调用swap函数的方法\n交换前：cc = " << cc << ",dd = " << dd << endl;
    swap(cc, dd);
    cout << "交换后：cc = " << cc << ",dd = " <<dd << endl;
    return 0;
}
*/

//模板的使用
/*
#include<iostream>
using namespace std;
template<class T>
T Add(const T& x,const T& y)
{
    return x + y;
}
int main()
{
    int x = 6, y = 8;
    double a = 6.6, b = 8.8;
    cout << Add<int>(x, y) << endl;                      //强制调用模板
    cout << Add(x, y) << endl;                           //有模板会调用模板，
    //cout << Add(x, b) << endl;                         //不同参数类型存在歧义，会报错
    //上述报错代码的解决方案,
    cout << Add(x, (int)b) << endl;
    cout << Add((double)x, b) << endl;
    //常用下面的方法，称为显式实例化
    cout << Add<double>(x, b) << endl;
    cout << Add<int>(x, b) << endl;
    return 0;
}
*/

//调用模板写两份参数，则不会出现上述的歧义
/*
#include<iostream>
using namespace std;

template<class T1,class T2>
T1 Add(T1& x, T2& y)
{
    return x + y;
}

int main()
{
    int x = 3, y = 4;
    double a = 2.6, b = 3.5;
    char c = 'x', d = 'y';
    cout<<Add<>(x, b) << endl;             //
    cout << Add<int>(x, b) << endl;        //强制调用模板
    return 0;
}
*/

//类模板
/*
#include<iostream>
using namespace std;
template<class T>
class Stack
{
public:
    Stack()
        :_a(nullptr)
        ,_top(0)
        ,_capacity(0)
    {}

    void push(const T& x)
    {
        //.......
    }
private:
    T* _a;
    int _top;
    int _capacity;
};

int main()
{
    //只能显示实例化,下面是同一个类模板的两个实例化类型
    Stack<int> st1;
    Stack<double> st1;
    return 0;
}
*/


//什么是STL?
// STL(standard template libaray-标准模板库)：是C++标准库的重要组成部分，不仅是一个可复用的组件库，
// 而且是一个包罗数据结构与算法的软件框架

//STL六大件：仿函数、算法、迭代器、空间配置、容器、分配器

//string类对象的常见构造
/*
#include<iostream>
#include<string>
using namespace std;

int main()
{
    string s0;                                    //默认构造
    string s1("helle world!");                    //设置字符hello world!
    string s2(s1);                                //拷贝构造
    string s3(s1, 5, 3);                          //拷贝s1,从第5个位置取3个字符
    string s4(s1, 5, 10);                         //拷贝s1,从第5个位置取10个字符,超过s1的字符，则s1有多少字符取多少
    string s5(s1, 5);                             //拷贝s1,从第5个位置取字符
    string s6(10, '#');                           //构造10个 '#'字符

    cout << "s0 = " << s0 << endl;
    cout << "s1 = " << s1 << endl;
    cout << "s2 = " << s2 << endl;
    cout << "s3 = " << s3 << endl;
    cout << "s4 = " << s4 << endl;
    cout << "s5 = " << s5 << endl;
    cout << "s6 = " << s6 << endl<<endl;

    //string方式
    string s7("hello world!");
    s0 = s7;
    cout << "s0 = " << s0 << endl;
    return 0;
}
*/

// string的遍历

/*
#include<iostream>
#include<string>
using namespace std;
class string_m                     //模拟string类
{
public:
    char& operator[](size_t pos)   //调用函数operator[]，返回的是第pos位置上的char类型的字符
    {
        return _str[pos];          //返回的是引用，方便调用，因此可以修改pos位置的字符
    }
private:
    char* _str;
    size_t _size;
    size_t _capacity;
};

void Test_string()               //遍历string s1的字符，下标法遍历
{
    string s1("hello world!");
    for (size_t i = 0; i < s1.size(); i++)
    {
        cout << s1[i] << " ";
    }
    cout << endl;
    //上述代码的底层原理是s1.operator[](i)，模拟的是数组访问的行为，即s1.operator[](i)等价于s1[i]

    for (size_t i = 0; i < s1.size(); i++)
    {
        cout << s1.operator[](i) << " ";       //这里的本质是调用函数operator[]，模拟数组访问行为
    }
    cout << endl;
    //上述两段代码打印的是一样的

    //修改字符
    for (size_t i = 0; i < s1.size(); i++)
    {
        s1[i]++;                    //修改
    }
    for (size_t i = 0; i < s1.size(); i++)
    {
        cout << s1[i] << " ";       //打印
    }
    cout << endl;
    
    //const string s2("hehexixi!");
    //for (size_t i = 0; i < s1.size(); i++)
    //{
    //    s2[i]++;                    //这里报错，因为const修饰后不能被修改
    //}
}

//使用迭代器的方式遍历string
void Test_string_1()
{
    cout << endl;
    string st1("hello world!");
    //使用标准迭代器遍历，行为类似指针的用法
    string::iterator it_st1 = st1.begin();        //调用st1.begin()是返回对象st1第一个位置的数据
    while (it_st1!=st1.end())                     //调用st1.end()是返回最后一个数据的下一个位置，也就是'\0'的位置
    {
        cout << *it_st1 << " ";
        ++it_st1;
    }
    cout << endl;

    //也可以使用迭代器修改内容，迭代器是容器的主流遍历方式
    string st2("hello world!");
    string::iterator it_st2 = st2.begin();
    while (it_st2 != st2.end())                     
    {      
        *it_st2-=3;                              //对每个字符的位置进行修改
        ++it_st2;
    }
    it_st2= st2.begin();
    while (it_st2 != st2.end())                    
    {
        cout << *it_st2 << " ";
        ++it_st2;
    }
    cout << endl;
}

int main()
{
    Test_string();
    Test_string_1();
}
*/

//迭代器的通用法则
/*
#include<iostream>
#include<vector>
#include<list>
using namespace std;

void Test_string()
{
    string st1("hello world!");
    string::iterator it_st1 = st1.begin();
    while (it_st1 != st1.end())
    {
        cout << *it_st1 << " ";
        ++it_st1;
    }
    cout << endl;

    //调用范围for的方式，其底层还是迭代器，只是代码更加简洁
    for (auto e : st1)
    {
        cout << e << " ";
    }
    cout << endl;
}

void Test_list()
{
    vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    v.push_back(5);
    vector<int>::iterator it_v = v.begin();
    while (it_v != v.end())
    {
        cout << *it_v << " ";
        ++it_v;
    }
    cout << endl;

    //调用范围for的方式，其底层还是迭代器，只是代码更加简洁
    for (auto e : v)
    {
        cout << e << " ";
    }
    cout << endl;
}

void Test_vector()
{
    list<int> lt;
    lt.push_back(11);
    lt.push_back(12);
    lt.push_back(13);
    lt.push_back(14);
    lt.push_back(15);
    list<int>::iterator it_lt = lt.begin();
    while (it_lt != lt.end())
    {
        cout << *it_lt << " ";
        ++it_lt;
    }
    cout << endl;

    //调用范围for的方式，其底层还是迭代器，只是代码更加简洁
    for (auto e : lt)
    {
        cout << e << " ";
    }
    cout << endl;
}

int main()                                                  //主函数
{   //迭代器的简单使用和范围for的使用
    Test_string();                          
    Test_list();
    Test_vector();
    return 0;
}
*/